package com.zlc.common.util;

import okhttp3.FormBody;
import okhttp3.Headers;
import okhttp3.MediaType;
import okhttp3.MultipartBody;
import okhttp3.OkHttpClient;
import okhttp3.Request;
import okhttp3.RequestBody;
import okhttp3.Response;
import okhttp3.ResponseBody;
import org.springframework.util.ObjectUtils;

import javax.servlet.http.HttpServletRequest;
import java.io.File;
import java.io.IOException;
import java.io.InputStream;
import java.util.Enumeration;
import java.util.HashMap;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.concurrent.TimeUnit;

/**
 * http 调用工具  基于okHttp
 *
 * @author zl
 */
public final class HttpUtils {


    private static final String ERROR_MSG = "{\"code\":-1,\"msg\":\"error request\"}";

    private static final String JSON_CONTENT_TYPE = "application/json; charset=utf-8";

    private static final String WWW_FORM_CONTENT_TYPE = "application/x-www-form-urlencoded; charset=utf-8";

    private static final String FORM_DATA_CONTENT_TYPE = "multipart/form-data; charset=utf-8";

    private static final String POST = "POST";

    private static final String PUT = "PUT";

    private static final String DELETE = "DELETE";

    public static final String PATCH = "PATCH";

    public static final String CONTENT_TYPE = "Content-Type";


    private HttpUtils(){}

    /**
     * 获取请求中的param参数 返回map
     */
    public static Map<String,Object> getRequestParam(HttpServletRequest request){
        Map<String,Object> receiveMap = new HashMap<String,Object>();
        Enumeration<String> enu = request.getParameterNames();
        while (enu.hasMoreElements()) {
            String key = String.valueOf(enu.nextElement());
            String value = request.getParameter(key);
            receiveMap.put(key, value);
        }
        return receiveMap;
    }


    /**
     * get请求
     * @param url  请求地址
     */
    public static String getResult(String url){
        return getResult(url,null,null,60,10,TimeUnit.SECONDS);
    }


    public static String getResult(String url,Map<String,Object> args){
        return getResult(url,args,null,60,10,TimeUnit.SECONDS);
    }


    public static String getResult(String url,Map<String,Object> args,Map<String,String> httpHeaders){
        return getResult(url,args,httpHeaders,60,10,TimeUnit.SECONDS);
    }

    /**
     * get请求
     * @param url  请求地址
     */
    public static InputStream getStream(String url){
        return getStream(url,null,null,60,10,TimeUnit.SECONDS);
    }


    public static InputStream getStream(String url,Map<String,Object> args){
        return getStream(url,args,null,60,10,TimeUnit.SECONDS);
    }


    public static InputStream getStream(String url,Map<String,Object> args,Map<String,String> httpHeaders){
        return getStream(url,args,httpHeaders,60,10,TimeUnit.SECONDS);
    }


    /**
     * @param url 请求地址
     * @param args  请求参数
     * @param  httpHeaders 请求头
     * @param connectTimeout 请求连接超时时间  单位秒
     * @param readTimeout 读取数据超时时间  单位秒
     * @param timeUnit 时间单位
     *
     * @return string
     */
    public static String getResult(String url, Map<String,Object> args,Map<String,String> httpHeaders, int connectTimeout,int readTimeout,TimeUnit timeUnit){
        ResponseBody body = getBody(url,args,httpHeaders,connectTimeout,readTimeout,timeUnit);
        if(!ObjectUtils.isEmpty(body)){
            try {
                return body.string();
            }catch (Exception e){
                e.printStackTrace();
                return ERROR_MSG;
            }
        }
        return ERROR_MSG;
    }


    public static InputStream getStream(String url, Map<String,Object> args,Map<String,String> httpHeaders, int connectTimeout,int readTimeout,TimeUnit timeUnit){
        ResponseBody body = getBody(url,args,httpHeaders,connectTimeout,readTimeout,timeUnit);
        if(!ObjectUtils.isEmpty(body)){
            try {
                return body.byteStream();
            }catch (Exception e){
                e.printStackTrace();
                return null;
            }
        }
        return null;
    }


    private static ResponseBody getBody(String url, Map<String,Object> args,Map<String,String> httpHeaders, int connectTimeout,int readTimeout,TimeUnit timeUnit){
        //请求客户端
        OkHttpClient client = new OkHttpClient.Builder()
                .connectTimeout(connectTimeout, timeUnit)
                .readTimeout(readTimeout,timeUnit)
                .build();

        //请求内容
        Request.Builder requestBuilder = new Request.Builder();
        requestBuilder
                .get();
        if(!ObjectUtils.isEmpty(args)){
            requestBuilder.url(loadUrl(url,args));
        }else{
            requestBuilder.url(url);
        }

        if(!ObjectUtils.isEmpty(httpHeaders)){
            requestBuilder
                    .headers(Headers.of(httpHeaders));
        }

        try {
            //开始请求
            Response response = client.newCall(requestBuilder.build()).execute();
            ResponseBody body =  response.body();

            if(!ObjectUtils.isEmpty(body)){
                return body;
            }else{
                return null;
            }
        } catch (IOException e) {
            e.printStackTrace();
        }

        return null;
    }


    private static String loadUrl(String url,Map<String,Object> args){
        if(ObjectUtils.isEmpty(url)){
            return "";
        }
        if(!url.endsWith("?")){
            url = url + "?";
        }
        StringBuilder builder = new StringBuilder(url);
        Set<Map.Entry<String,Object>> entrySet = args.entrySet();
        Iterator<Map.Entry<String,Object>> iterator = entrySet.iterator();
        while(iterator.hasNext()){
            Map.Entry<String,Object> node = iterator.next();
            String key = node.getKey();
            Object value = node.getValue();
            builder.append(key)
                    .append("=")
                    .append(String.valueOf(value));
            if(iterator.hasNext()){
                builder.append("&");
            }
        }
        return builder.toString();
    }


    public static String postJson(String url,Object data){
        return postJson(url,data,null,60,10,TimeUnit.SECONDS);
    }

    public static String postJson(String url,Object data,Map<String,String> httpHeaders){
        return postJson(url,data,httpHeaders,60,10,TimeUnit.SECONDS);
    }

    public static String postForm(String url,Map<String,Object> data){
        return postForm(url,data,null,60,10,TimeUnit.SECONDS);
    }

    public static String postForm(String url,Map<String,Object> data,Map<String,String> httpHeaders){
        return postForm(url,data,httpHeaders,60,10,TimeUnit.SECONDS);
    }


    public static String postFormFile(String url,List<File> files){
        return postFormFile(url,files,null,null,60 * 5,60,TimeUnit.SECONDS);
    }


    public static String postFormFile(String url,List<File> files,Map<String,Object> data){
        return postFormFile(url,files,data,null,60 * 5,60,TimeUnit.SECONDS);
    }

    public static String postFormFile(String url,List<File> files,Map<String,Object> data,Map<String,String> httpHeaders){
        return postFormFile(url,files,data,httpHeaders,60 * 5,60,TimeUnit.SECONDS);
    }



    public static String putJson(String url,Object data){
        return putJson(url,data,null,60,10,TimeUnit.SECONDS);
    }

    public static String putJson(String url,Object data,Map<String,String> httpHeaders){
        return putJson(url,data,httpHeaders,60,10,TimeUnit.SECONDS);
    }

    public static String putForm(String url,Map<String,Object> data){
        return putForm(url,data,null,60,10,TimeUnit.SECONDS);
    }

    public static String putForm(String url,Map<String,Object> data,Map<String,String> httpHeaders){
        return putForm(url,data,httpHeaders,60,10,TimeUnit.SECONDS);
    }


    public static String deleteJson(String url,Object data){
        return deleteJson(url,data,null,60,10,TimeUnit.SECONDS);
    }

    public static String deleteJson(String url,Object data,Map<String,String> httpHeaders){
        return deleteJson(url,data,httpHeaders,60,10,TimeUnit.SECONDS);
    }

    public static String deleteForm(String url,Map<String,Object> data){
        return deleteForm(url,data,null,60,10,TimeUnit.SECONDS);
    }

    public static String deleteForm(String url,Map<String,Object> data,Map<String,String> httpHeaders){
        return deleteForm(url,data,httpHeaders,60,10,TimeUnit.SECONDS);
    }

    /**
     * post  json参数请求
     *
     * @param url                    地址
     * @param data                   参数
     * @param httpHeaders            请求头
     * @param connectTimeout         连接超时时间
     * @param readTimeout            读取超时时间
     * @param timeUnit               时间单位
     * @return   string
     */
    public static String deleteJson(String url,Object data,Map<String,String> httpHeaders, int connectTimeout,int readTimeout,TimeUnit timeUnit ){
        ResponseBody responseBody = result(url,DELETE,JSON_CONTENT_TYPE,data,httpHeaders,connectTimeout,readTimeout,timeUnit);
        if(responseBody == null){
            return ERROR_MSG;
        }else{
            try {
                return responseBody.string();
            }catch (Exception e){
                e.printStackTrace();
            }
        }
        return ERROR_MSG;
    }

    /**
     * post  application/x-www-form-urlencoded参数请求
     *
     * @param url                    地址
     * @param data                   参数
     * @param httpHeaders            请求头
     * @param connectTimeout         连接超时时间
     * @param readTimeout            读取超时时间
     * @param timeUnit               时间单位
     * @return   string
     */
    public static String deleteForm(String url,Map<String,Object> data,Map<String,String> httpHeaders, int connectTimeout,int readTimeout,TimeUnit timeUnit ){
        ResponseBody responseBody = result(url,DELETE,WWW_FORM_CONTENT_TYPE,data,httpHeaders,connectTimeout,readTimeout,timeUnit);
        if(responseBody == null){
            return ERROR_MSG;
        }else{
            try {
                return responseBody.string();
            }catch (Exception e){
                e.printStackTrace();
            }
        }
        return ERROR_MSG;
    }


    /**
     * post  json参数请求
     *
     * @param url                    地址
     * @param data                   参数
     * @param httpHeaders            请求头
     * @param connectTimeout         连接超时时间
     * @param readTimeout            读取超时时间
     * @param timeUnit               时间单位
     * @return   string
     */
    public static String putJson(String url,Object data,Map<String,String> httpHeaders, int connectTimeout,int readTimeout,TimeUnit timeUnit ){
        ResponseBody responseBody = result(url,PUT,JSON_CONTENT_TYPE,data,httpHeaders,connectTimeout,readTimeout,timeUnit);
        if(responseBody == null){
            return ERROR_MSG;
        }else{
            try {
                return responseBody.string();
            }catch (Exception e){
                e.printStackTrace();
            }
        }
        return ERROR_MSG;
    }

    /**
     * post  application/x-www-form-urlencoded参数请求
     *
     * @param url                    地址
     * @param data                   参数
     * @param httpHeaders            请求头
     * @param connectTimeout         连接超时时间
     * @param readTimeout            读取超时时间
     * @param timeUnit               时间单位
     * @return   string
     */
    public static String putForm(String url,Map<String,Object> data,Map<String,String> httpHeaders, int connectTimeout,int readTimeout,TimeUnit timeUnit ){
        ResponseBody responseBody = result(url,PUT,WWW_FORM_CONTENT_TYPE,data,httpHeaders,connectTimeout,readTimeout,timeUnit);
        if(responseBody == null){
            return ERROR_MSG;
        }else{
            try {
                return responseBody.string();
            }catch (Exception e){
                e.printStackTrace();
            }
        }
        return ERROR_MSG;
    }


    /**
     * post  json参数请求
     *
     * @param url                    地址
     * @param data                   参数
     * @param httpHeaders            请求头
     * @param connectTimeout         连接超时时间
     * @param readTimeout            读取超时时间
     * @param timeUnit               时间单位
     * @return   string
     */
    public static String postJson(String url,Object data,Map<String,String> httpHeaders, int connectTimeout,int readTimeout,TimeUnit timeUnit ){
        ResponseBody responseBody = result(url,POST,JSON_CONTENT_TYPE,data,httpHeaders,connectTimeout,readTimeout,timeUnit);
        if(responseBody == null){
            return ERROR_MSG;
        }else{
            try {
                return responseBody.string();
            }catch (Exception e){
                e.printStackTrace();
            }
        }
        return ERROR_MSG;
    }

    /**
     * post  application/x-www-form-urlencoded参数请求
     *
     * @param url                    地址
     * @param data                   参数
     * @param httpHeaders            请求头
     * @param connectTimeout         连接超时时间
     * @param readTimeout            读取超时时间
     * @param timeUnit               时间单位
     * @return   string
     */
    public static String postForm(String url,Map<String,Object> data,Map<String,String> httpHeaders, int connectTimeout,int readTimeout,TimeUnit timeUnit ){
        ResponseBody responseBody = result(url,POST,WWW_FORM_CONTENT_TYPE,data,httpHeaders,connectTimeout,readTimeout,timeUnit);
        if(responseBody == null){
            return ERROR_MSG;
        }else{
            try {
                return responseBody.string();
            }catch (Exception e){
                e.printStackTrace();
            }
        }
        return ERROR_MSG;
    }

    /**
     * post  application/x-www-form-urlencoded参数请求
     *
     * @param url                    地址
     * @param files                   文件
     * @param httpHeaders            请求头
     * @param connectTimeout         连接超时时间
     * @param readTimeout            读取超时时间
     * @param timeUnit               时间单位
     * @return   string
     */
    public static String postFormFile(String url,List<File> files,Map<String,Object> data,Map<String,String> httpHeaders, int connectTimeout,int readTimeout,TimeUnit timeUnit ){
        Map<String,Object> args = new HashMap<>();
        args.put("file",files);
        args.putAll(data);
        ResponseBody responseBody = result(url,POST,FORM_DATA_CONTENT_TYPE,args,httpHeaders,connectTimeout,readTimeout,timeUnit);
        if(responseBody == null){
            return ERROR_MSG;
        }else{
            try {
                return responseBody.string();
            }catch (Exception e){
                e.printStackTrace();
            }
        }
        return ERROR_MSG;
    }


    /**
     * post 以及请求请求方式
     *
     * @param url   地址
     * @param requestMethod  请求方式
     * @param contentType  参数类型
     * @param args   参数
     * @param httpHeaders  请求头
     * @param connectTimeout  连接请求超时时间
     * @param readTimeout   读取数据超时时间
     * @param timeUnit 时间单位
     * @return  string
     */
    private static ResponseBody result(String url,String requestMethod, String contentType, Object args
            , Map<String,String> httpHeaders, int connectTimeout, int readTimeout, TimeUnit timeUnit){
        //请求客户端
        OkHttpClient client = new OkHttpClient.Builder()
                .connectTimeout(connectTimeout, timeUnit)
                .readTimeout(readTimeout,timeUnit)
                .build();

        //请求内容
        //builder
        Request.Builder requestBuilder = new Request.Builder()
                .url(url);
        RequestBody requestBody = null;
        if(contentType.equals(JSON_CONTENT_TYPE)){
            String json = JsonHelper.toJson(args);
            requestBody = RequestBody.create(MediaType.parse(JSON_CONTENT_TYPE), json);
        } else if (contentType.equals(WWW_FORM_CONTENT_TYPE)) {
            if(args instanceof Map) {
                Map<String,Object> variable = (Map<String, Object>) args;
                FormBody.Builder builder = new FormBody.Builder();
                for (Map.Entry<String, Object> map : variable.entrySet()) {
                    builder.add(map.getKey(), String.valueOf(map.getValue()));
                }
                requestBody = builder.build();
            }
            requestBuilder.header(CONTENT_TYPE,WWW_FORM_CONTENT_TYPE);


        } else if (contentType.equals(FORM_DATA_CONTENT_TYPE)) {
            MediaType MutilPart_Form_Data = MediaType.parse(FORM_DATA_CONTENT_TYPE);
            Map<String,Object> data = (Map<String, Object>) args;
            //取出文件
            Object fileObjs = data.get("file");
            data.remove("file");

            MultipartBody.Builder requestBodyBuilder = new MultipartBody.Builder()
                    .setType(MultipartBody.FORM);
            //FORM DATA
            if(fileObjs instanceof List) {
                List<Object> files = (List<Object>) fileObjs;
                for(Object f : files) {
                    if(f instanceof File){
                        File file = (File) f;
                        requestBodyBuilder.addFormDataPart("files", file.getName(), RequestBody.create(MutilPart_Form_Data,file));
                    }
                }
            }
            for (Map.Entry<String, Object> map : data.entrySet()) {
                requestBodyBuilder.addFormDataPart(map.getKey(), String.valueOf(map.getValue()));
            }

            requestBody = requestBodyBuilder.build();
        }

        if(!ObjectUtils.isEmpty(httpHeaders)){
            requestBuilder.headers(Headers.of(httpHeaders));
        }

        switch (requestMethod) {
            case POST:
                requestBuilder.post(requestBody);
                break;
            case PUT:
                requestBuilder.put(requestBody);
                break;
            case DELETE:
                requestBuilder.delete(requestBody);
                break;
            case PATCH:
                requestBuilder.patch(requestBody);
                break;
            default:break;
        }

        try {

            return client.newCall(requestBuilder.build()).execute().body();
        }catch (Exception e){
            e.printStackTrace();
            return null;
        }
    }


    public static void main(String[] args) {
        Map<String,Object> map = new HashMap<>();
        map.put("page",1);
        map.put("limit",10);
        map.put("key","mysql");
        String result = getResult("http://www.abcd123.com/web/doc/list",map,null,10,3,TimeUnit.SECONDS);
        Map<String,String> headers = new HashMap<>();
        headers.put("token","48fdjharjkehwjrhewjkrjwkhrekwrew");
        headers.put("userInfo","{}");
//        postForm("http://localhost:9300/gzh/dev/save",map);
//        postFormFile("http://localhost:9300/gzh/dev/saveFile",Collections.singletonList(new File("D:\\图片\\timg.jpg")),map);4
        InputStream stream = getStream("https://img-blog.csdnimg.cn/20190223092313758.png");

        System.out.println(result);
    }



}
